package com.zmj.sy.mom.srv.aps.config;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogContent;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogSystem;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseResVo;
import com.zmj.sy.mom.srv.aps.lock.BaseAspect;
import com.zmj.sy.mom.srv.aps.mapper.LogContentMapper;
import com.zmj.sy.mom.srv.aps.mapper.LogSystemMapper;
import com.zmj.sy.mom.srv.aps.utils.WorkshopProp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 数据库日志记录
 *
 * @author 2019年6月18日
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class LogContentDbAspect extends BaseAspect {
    private final HttpServletRequest request;
    private static final String SERVER_NAME = "mom-srv-aps";
    private final ObjectMapper objectMapper;
    private final LogSystemMapper logSystemMapper;
    private final LogContentMapper logContentMapper;

    /***
     * 定义controller切入点拦截规则，拦截zmjsyRepeat注解的业务方法
     */
    @Pointcut("@annotation(logContent)")
    public void pointCut(AspectLog logContent) {
    }

    /**
     * AOP分布式锁拦截
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    @Around("pointCut(logContent)")
    public Object repeatSubmit(ProceedingJoinPoint joinPoint, AspectLog logContent) throws Throwable {

        String url = request.getRequestURI();
        String queryString = request.getQueryString();

        long start = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();
        Object result = null;
        boolean success = false;
        String error = null;
        try {
            result = joinPoint.proceed();
            if (result instanceof BaseResVo) {
                ((BaseResVo) result).setCode(BaseResVo.SUCCESS_CODE);
            }

            success = true;
        } catch (Throwable e) {
            error = e.getMessage();
            throw e;
        } finally {
            String req = args == null ? "" : objectMapper.writeValueAsString(args);
            LogSystem logApi = new LogSystem();
            logApi.setApiName(logContent.apiName());
            logApi.setAppId(SERVER_NAME);
            logApi.setUrl(url);
            logApi.setOperationType(logContent.operationType());
            logApi.setSuccess(success);
            if (StringUtils.isBlank(queryString)) {
                logApi.setQueryParam(req.length() > WorkshopProp.LOG_SIZE ? req.substring(0, WorkshopProp.LOG_SIZE) : req);
            } else {
                logApi.setQueryParam(queryString);
            }
//            logApi.setRequestPath(req);
            Long reqTime = (System.currentTimeMillis() - start);
            logApi.setWorkTime(reqTime);
            String res = result == null ? "" : objectMapper.writeValueAsString(result);
            if (!success) {
                res = error;
            }
            if (res != null) {
                logApi.setResponsePath(res.length() > WorkshopProp.LOG_SIZE ? res.substring(0, WorkshopProp.LOG_SIZE) : res);
                logSystemMapper.insert(logApi);
                if (res.length() > WorkshopProp.LOG_SIZE || req.length() > WorkshopProp.LOG_SIZE) {
                    LogContent con = new LogContent();
                    con.setReqContent(objectMapper.writeValueAsString(args));
                    con.setResContent(objectMapper.writeValueAsString(result));
                    con.setLogType(1);
                    con.setLogId(logApi.getId());
                    logContentMapper.insert(con);
                }
            }


        }
        return result;
    }


}
